﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace Submarines
{
    class Player : Board
    {
        enum VectorStatus
        {
            TryUp,
            TryDown,
            TryLeft,
            TryRight,
        }

        Button _Source;
        Color _OldBackColor;
        VectorStatus _Vector;
        int _x, _y;
        bool _Left = false;
        bool _Up = false;
        bool _VectorFound = false;
        bool _TryingVector;
        bool[] _VectorsTried = { false, false, false, false };
        StepResult _Step = StepResult.Failed;
        Random r = new Random();

        //protected override void OnMouseClick(object sender, MouseEventArgs e)
        //{
        //    if ((e.Button & MouseButtons.Left) != MouseButtons.Left) return;

        //    Button button = ((Button)sender);

        //    if ((CellStatus)button.Tag == CellStatus.PartOfSubmarine)
        //    {
        //        button.Tag = CellStatus.Hit;
        //        button.BackColor = _HitColor;
        //        /////////////////////////
        //        _x = GetX(button.Name);
        //        _y = GetY(button.Name);
        //        _TryingVector = true;
        //        /////////////////////////
        //    }
        //    else button.Visible = false;
        //}

        void ResetVectors()
        {
            for (int a = 0; a < 4; a++) _VectorsTried[a] = false;
        }

        VectorStatus RandomVector()
        {
            int tmp;
            do
            {
                tmp = r.Next(0, 4);

                if (_VectorsTried[0] == true && _VectorsTried[1] == true && _VectorsTried[2] == true && _VectorsTried[3] == true)
                    break;
            }
            while (_VectorsTried[tmp] == true);

            _VectorsTried[tmp] = true;

            return (VectorStatus)tmp;
        }

        void FindVector()
        {
            _VectorFound = false;
            _TryingVector = true;
            do
            {
                if (_VectorsTried[0] == true && _VectorsTried[1] == true && _VectorsTried[2] == true && _VectorsTried[3] == true)
                {
                    ResetVectors();
                    _TryingVector = false;
                    _VectorFound = false;
                    break;
                }

                _Vector = RandomVector();
                switch (_Vector)
                {
                    case VectorStatus.TryUp:
                        _Step = TryToHit(_x, _y - 1); // try upper cell
                        if (_Step == StepResult.Hit)
                        {
                            _VectorFound = true;
                            _TryingVector = false;
                            _y--;
                        }
                        break;
                    case VectorStatus.TryDown:
                        _Step = TryToHit(_x, _y + 1); // try lower cell
                        if (_Step == StepResult.Hit)
                        {
                            _VectorFound = true;
                            _TryingVector = false;
                            _y++;
                        }
                        break;
                    case VectorStatus.TryLeft:
                        _Step = TryToHit(_x - 1, _y); // try left cell
                        if (_Step == StepResult.Hit)
                        {
                            _VectorFound = true;
                            _TryingVector = false;
                            _x--;
                        }
                        break;
                    case VectorStatus.TryRight:
                        _Step = TryToHit(_x + 1, _y); // try right cell
                        if (_Step == StepResult.Hit)
                        {
                            _VectorFound = true;
                            _TryingVector = false;
                            _x++;
                        }
                        break;
                }
            }
            while (_Step == StepResult.Failed);
        }

        bool TryUpCell()
        {
            CellStatus status;

            do
            {
                _y--;
                status = GetCellStatus(_x, _y);
            }
            while (status == CellStatus.Hit);

            if (status == CellStatus.Illegal || status == CellStatus.Empty)
            {
                _y++;
                return false;
            }
            return true;
        }

        bool TryDownCell()
        {
            CellStatus status;

            do
            {
                _y++;
                status = GetCellStatus(_x, _y);
            }
            while (status == CellStatus.Hit);

            if (status == CellStatus.Illegal || status == CellStatus.Empty)
            {
                _y--;
                return false;
            }
            return true;
        }

        bool TryLeftCell()
        {
            CellStatus status;

            do
            {
                _x--;
                status = GetCellStatus(_x, _y);
            }
            while (status == CellStatus.Hit);

            if (status == CellStatus.Illegal || status == CellStatus.Empty)
            {
                _x++;
                return false;
            }
            return true;
        }

        bool TryRightCell()
        {
            CellStatus status;

            do
            {
                _x++;
                status = GetCellStatus(_x, _y);
            }
            while (status == CellStatus.Hit);

            if (status == CellStatus.Illegal || status == CellStatus.Empty)
            {
                _x--;
                return false;
            }
            return true;
        }

        void TryByVector()
        {
            bool Vertical = (_Vector == VectorStatus.TryDown || _Vector == VectorStatus.TryUp);

            if (Vertical)
            {
                if (GetCellStatus(_x, _y) == CellStatus.Empty)
                    _Up = !_Up;
                else
                    _Up = r.Next(0, 2) == 0;

                if (_Up)
                {
                    if (TryUpCell() == false)
                        TryDownCell();
                }
                else
                {
                    if (TryDownCell() == false)
                        TryUpCell();
                }
            }
            else
            {
                if (GetCellStatus(_x, _y) == CellStatus.Empty)
                    _Left = !_Left;
                else
                    _Left = r.Next(0, 2) == 0;

                if (_Left)
                {
                    if (TryLeftCell() == false)
                        TryRightCell();
                }
                else
                {
                    if (TryRightCell() == false)
                        TryLeftCell();
                }
            }

            _Step = TryToHit(_x, _y);
        }

        void ComputeNextStep()
        {
            if (_VectorFound)
                TryByVector();
            else
                FindVector();
        }

        void RandomNextStep()
        {
            do
            {
                _x = r.Next(0, 10);
                _y = r.Next(0, 10);
                _Step = TryToHit(_x, _y);
            }
            while (_Step == StepResult.Failed);

            if (_Step == StepResult.Hit)
                _TryingVector = true;
        }

        public void Next()
        {
            if (IsGameOver()) return;

            do
            {
                if (_VectorFound || _TryingVector)
                    ComputeNextStep();
                else
                    RandomNextStep();

                if (_Step == StepResult.Killed)
                {
                    _VectorFound = false;
                    _TryingVector = false;
                    ResetVectors();
                }
            }
            while (_Step == StepResult.Hit || _Step == StepResult.Killed);
        }

        void UpdateDetails(Button source)
        {
            string type = source.Name.Substring(0, 1);
            string size = source.Name.Substring(1, 1);
            Setup setup = source.Parent as Setup;

            int Amount = int.Parse((string)setup.Controls[type + size].Tag) - 1;
            setup.Controls[type + size].Tag = Amount.ToString();
            if (Amount == 0) setup.Controls[type + size].Enabled = false;

            if (type == "H") type = "V"; else type = "H";

            setup.Controls["H" + size].Text = (int.Parse(setup.Controls["H" + size].Text) - 1).ToString();
            setup.Controls["V" + size].Text = (int.Parse(setup.Controls["V" + size].Text) - 1).ToString();

            Amount = int.Parse((string)setup.Controls[type + size].Tag) - 1;
            setup.Controls[type + size].Tag = Amount.ToString();
            if (Amount == 0) setup.Controls[type + size].Enabled = false;

            setup._Done = true;
            for (int a = 0; a < 8; a++) if (setup.Controls[a].Enabled == true) setup._Done = false;
            if (setup._Done)
            {
                frmGame Form = setup.Parent as frmGame;
                Form.Controls["btnStart"].Visible = true;
            }
        }

        protected override void OnDragDrop(object sender, DragEventArgs e)
        {
            Button target = (Button)sender;
            Button source = (Button)e.Data.GetData(typeof(Button));

            int size = GetSize(source.Name);
            bool vertical = GetShape(source.Name);
            int x = GetX(target.Name);
            int y = GetY(target.Name);

            if (SubmarineValid(x, y, size, vertical))
            {
                e.Effect = DragDropEffects.Link;
                DrawSubmarine(x, y, size, vertical, _ExistColor);
                UpdateSubmarine(x, y, size, vertical, CellStatus.PartOfSubmarine);
                InstallSubmarine(size);
                UpdateDetails(source);
            }
        }

        protected override void OnDragLeave(object sender, EventArgs e)
        {
            Button target = (Button)sender;
            Button source = _Source;

            int size = GetSize(source.Name);
            bool vertical = GetShape(source.Name);
            int x = GetX(target.Name);
            int y = GetY(target.Name);

            if (SubmarineValid(x, y, size, vertical))
            {
                DrawSubmarine(x, y, size, vertical, _OldBackColor);
                UpdateSubmarine(x, y, size, vertical, CellStatus.Empty);
            }
        }

        protected override void OnDragEnter(object sender, DragEventArgs e)
        {
            Button target = (Button)sender;
            Button source = (Button)e.Data.GetData(typeof(Button));

            _Source = source;
            _OldBackColor = target.BackColor;

            int size = GetSize(source.Name);
            bool vertical = GetShape(source.Name);
            int x = GetX(target.Name);
            int y = GetY(target.Name);

            if (SubmarineValid(x, y, size, vertical))
            {
                e.Effect = DragDropEffects.Link;
                DrawSubmarine(x, y, size, vertical, _ShadowColor);
            }
            else e.Effect = DragDropEffects.None;
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // Player
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.DoubleBuffered = true;
            this.Name = "Player";
            this.ResumeLayout(false);

        }
    }
}
